Published on

5 分钟了解分区和分片

分区(partitioning)和分片(sharding)作为数据库系统扩展的可能策略,相关但又不同,本文介绍了两者的区别、权衡和实际应用。原文:Partitioning vs Sharding: Differences Every Engineer Must Know

当系统从数百万条记录增长到数十亿条记录时,就会不可避免的遇到性能和可扩展性瓶颈。在这个阶段,工程师通常会评估 分区(partitioning)分片(sharding) 作为可能的策略。两者相关但又不同,理解它们的差异对于设计数据密集型系统的人来说至关重要。

本文不仅仅停留在表面定义,还探讨了权衡、现实场景的使用模式以及在评估生产系统中分区与分片时可以应用的决策框架。

分区:在单一数据库中拆分数据

分区是一种将大型逻辑表拆分成更小、更易管理的部分(称为分区)的技术。数据库引擎管理这些分区,对应用程序来说,看起来仍然像一个单一的表。

分区类型(PostgreSQL 示例)

  • 范围分区 → 将行除以区间(例如,orders_2024orders_2025)。
  • 列分区 → 按显式值分组的行(例如,地区:美国、欧盟、亚太区)。
  • 哈希分区 → 使用哈希函数分配行,有助于均匀分布数据。

在该模式中,按年分区的订单查询仅涉及该年的分区,能显著减少 I/O 并提升性能。

优势

  • 通过分区裁剪提升了查询性能。
  • 维护更简便(例如,丢弃或归档分区)。
  • PostgreSQL 及其他 RDBMSS 中的原生支持。

局限性

  • 单节点约束:分区仍绑定在一台机器的 CPU、内存和磁盘上。
  • 单点故障:可能存在备份,但仍绑定在同一边界内。
  • 不是一个可扩展性解决方案:充其量是一种优化。

分片:跨多个数据库分发数据

分片扩展了跨多个数据库实例的分区概念。每个分片是一个独立数据库,存储部分数据。

工作原理

  • 定义分片键(例如,user_id)。
  • 路由器或中间件会将查询导向相应的分片。
  • 分片是独立的,可以独立扩展。

大型消息系统中的例子:

  • 分片 A → 用户 1–100M
  • 分片 B → 用户 10M–20M
  • 分片 C → 用户 20M–30M

查询 user_id = 18,000,000 将被直接路由到分片 B。

优势

  • 横向可扩展性:通过添加分片来扩展容量。
  • 故障隔离:一个分片的故障不一定会影响其他分片。
  • 灵活性:分片可以地理分布以降低延迟。

挑战

  • 应用复杂度:跨分片连接成本高昂甚至不可能实现。
  • 运维负担:模式变更、迁移和备份更为复杂。
  • 重分片:重新平衡分片既困难又常常带来干扰。

分区与分片

分区是在单个数据库实例中实现的,而分片跨越多个数据库实例。分区提升了可管理性和查询性能,但仅限于一台机器的限制。分片实现了真正的水平扩展,但引入了分布式系统的复杂性。

高级见解

  1. 分区是一种优化策略:提升了查询延迟和可维护性,但一旦达到单节点限制,效果就不大了。
  2. 分片引入了分布式系统的复杂性:一旦分片,就必须考虑 CAP 定理、分布式共识、复制延迟和运维开销。
  3. 选择合适的分片键至关重要:错误选择会导致分片分布不均和分片过热,经过深思熟虑的键能够平衡流量和存储。
  4. 成本影响:分区增加的开销较小,但基础设施中心化。分片增加了基础设施成本,但能实现近乎无限的水平增长。

实际应用

  • 金融系统:按日期对交易分区以进行报告;跨数据库对客户分片以应对规模化。
  • 电子商务:按时间分区订单数据,对客户和目录数据分片以实现全球覆盖。
  • 社交媒体:用户按 ID 分片,而每个分片内的帖子可能按时间分区。
  • 时间序列数据:分区数据库(例如 TimescaleDB)负责处理工作负载,存储卷强制采用分片。

要点总结

  • 分区将数据组织到一个数据库中以提升性能。
  • 分片将数据分布到数据库之间,实现真正的水平规模。
  • 选择不是非此即彼,而是权衡何时采纳。